import common.ListNode;

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */

/**
 * 92.  Reverse Linked List II 反转链表 II
 * https://leetcode-cn.com/problems/reverse-linked-list-ii/
 */
class ReverseLinkedListII {
    /**
     * 方法：迭代法，在需要反转的区间内，每次将cur.next节点移到区间开头
     *      一次遍历「穿针引线」反转链表（头插法）
     * 
     * Args:
     *   head: 链表头节点
     *   left: 反转区间的起始位置
     *   right: 反转区间的结束位置
     * 
     * Returns:
     *   反转指定区间后的链表头节点
     * 
     * Time: O(N)，其中N是链表总长度
     * 
     * Space: O(1)，只使用常数额外空间
     */
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode pre = dummy;
        for(int i = 0; i < left - 1; i++){
            pre = pre.next;
        }
        ListNode cur = pre.next;
        ListNode next;
        for(int i = 0; i < right - left; i++){
            next = cur.next;
            cur.next = next.next;
            next.next = pre.next;
            pre.next = next;
        }
        return dummy.next;
    }

    /**
     * 方法：反转链表的子区间
     * 
     * Args:
     *   head: 需要反转的链表头节点
     * 
     * Returns:
     *   反转后的链表头节点
     * 
     * Time: O(N)，其中N是链表总长度
     * 
     * Space: O(1)，只使用常数额外空间
     */
    public ListNode reverseBetween1(ListNode head, int left, int right) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;

        ListNode pre = dummy;
        // 第 1 步：从虚拟头节点走 left - 1 步，来到 left 节点的前一个节点
        for(int i = 0; i < left - 1; i++){
            pre = pre.next;
        }

        // 第 2 步：从 pre 再走 right - left + 1 步，来到 right 节点
        ListNode rightNode = pre;
        for(int i = 0; i < right - left +1; i++){
            rightNode = rightNode.next;
        }
        // 第 3 步：切断出一个子链表（截取链表）
        ListNode leftNode = pre.next;
        ListNode cur = rightNode.next;
        pre.next = null;
        rightNode.next = null;
        // 第 4 步：同第 206 题，反转链表的子区间
        reverseLinkedList(leftNode);
        // 第 5 步：接回到原来的链表中
        pre.next = rightNode;
        leftNode.next = cur;
        return dummy.next;
    }

    private void reverseLinkedList(ListNode head){
        if(head == null){
            return;
        }
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
    }
}